#include "String2Number.h"

// error: if the input is no number (e.g. char or string)  then error,
// if wrong input (integer expected but e.g. float given) then error
// changes string into integer:
int stoi( const string &s )
{
  int i;
  double temp; // temporary integer

  const char *pointer;
  pointer = s.c_str();
  istringstream ist( pointer );
  ist >> temp;
  // if ist==NULL (s in no number) then error:
  if( ist == NULL )
    {
      cerr << "\"" << s << "\" is no integer!!" << endl;
      ERROR( "Integer expected", exception); 
    }
  // if temp is no integer (temp-static_cast<int>(temp)!=0) then error: 
  if( (temp - static_cast<int>( temp )) != 0 )
    {
      cerr << "\"" << s << "\" is no integer!!" << endl;
      ERROR( "Wrong format", exception); 
    }
  i = static_cast<int>( temp );
  return i;
}

// author: Eckart Bindewald
// date: June 2, 1998
// description: same as stoi, but for unsigned int
// error: if the input is no number (e.g. char or string)  then error,
// if wrong input (integer expected but e.g. float given) then error
// changes string into integer:
unsigned int stoui( const string &s )
{
  unsigned int i;
  double temp; // temporary integer

  const char *pointer;
  pointer = s.c_str();
  istringstream ist( pointer );
  ist >> temp;
  // if ist==NULL (s in no number) then error:
  if( ist == NULL )
    { 
      cerr << "\"" << s << "\" is no unsigned integer!!" << endl;
      ERROR( "Integer expected", exception); 
    }
  // if temp is no integer (temp-static_cast<int>(temp)!=0) then error: 
  if( (temp - static_cast<unsigned int>( temp )) != 0 )
    { 
      cerr << "\"" << s << "\" is no unsigned integer!!" << endl;
      ERROR( "Wrong format", exception); 
    }
  if( temp < 0 )
    { ERROR( "Negative unsigned integer", exception); }
  i = static_cast<unsigned int>( temp );
  return i;
}


// error: if the input is no number (e.g. char or string)  then error,
// if wrong input (long expected but e.g. float given) then error
// changes string into long:
long stol( const string &s )
{
  long l;
  long double temp; // temporary integer

  const char *pointer;
  pointer = s.c_str();
  istringstream ist( pointer );
  ist >> temp;
  // if ist==NULL (s in no number) then error:
  if( ist == NULL )
    {
      cerr << "\"" << s << "\" is no long integer!!" << endl; 
      ERROR( "Long expected", exception); 
    }
  // if temp is no long (temp-static_cast<long>(temp)!=0) then error: 
  if( (temp - static_cast<long>( temp )) != 0 )
    {
      cerr << "\"" << s << "\" is no long integer!!" << endl; 
      ERROR( "Wrong format", exception); 
    }
  l = static_cast<long>( temp );
  return l;
}

// error: if the input is no number (e.g. char or string)  then error,
// if wrong input (float expected but e.g. double given) then error
// changes string into float:
float stof( const string &s )
{
  float f;
  float temp; // temporary integer

  const char *pointer;
  pointer = s.c_str();
  istringstream ist( pointer );
  ist >> temp;
  // if ist==NULL (s is no number) then error:
  if( ist == NULL )
    { 
      cerr << "\"" << s << "\" is no float!!" << endl;
      ERROR( "Float expected", exception); 
    }
  // if temp is no long (temp-static_cast<float>(temp)!=0) then error: 
  if( (temp - static_cast<float>( temp )) != 0 )
    {
      cerr << "\"" << s << "\" is no float!!" << endl;
      ERROR( "Wrong format", exception); 
    }
  f = temp;
  return f;
}

// error: if the input is no number (e.g. char or string)  then error
// changes string into double:
double stod( const string &s )
{
  double d;
  double temp; // temporary integer

  const char *pointer;

  string temp_s;
  if (s == "e-99") {
      temp_s = "1e-99";
      pointer = temp_s.c_str();
  }

  else pointer = s.c_str();

  istringstream ist( pointer );

//   if (ist.str() = "e-99") {
//       stringstream ist_new;
//       ist_new << "1e-99"
//       ist_new >> temp;
//   }

//   else
      
  ist >> temp;

  // if ist==NULL (s is no number) then error:
  if( ist == NULL )
    {
      cerr << "\"" << s << "\" is no double!!" << endl;
      ERROR( "Wrong format", exception); 
    }
  d = temp;
  return d;
}

// -----------------------------------------------------------
// author: Eckart Bindewald
// date: May 13, 1998
// name of function: sToVectorOfInt
// description:
// changes string to vector of integer. Format: n1,n2,n3, ...
// precondition: spaces between numbers. String can also be enclosed in "..."
// postcondition: the return vector is filled with the apropriate numbers
// error behaviour: quits, if precondition is not fullfilled.
// -----------------------------------------------------------
vector<int> sToVectorOfInt( const string& s_orig) {
  string s = s_orig;
  vector<int> v;
  if (s[1] == '\'') {
    DEBUG_MSG("Removing colons!");
    ASSERT(s[s.size()-1]=='\'',exception);
#ifdef G_COMPILER
    s.remove( 0U, 1U ); // remove the first letter
    s.remove(s.size()-1U,1U); // remove last letter
#else
    s.erase( 0, 1 ); // remove the first letter
    s.erase(s.size()-1,1); 
#endif
  }
  istringstream ist(s.c_str()); // see Stroustrup chapter 21.5.3
  string w; // word
  while (ist >> w) {
    v.push_back(stoi(w));
    DUMP(w);
  }
  return v;
}

// -----------------------------------------------------------
// author: Eckart Bindewald
// date: May 13, 1998
// name of function: sToVectorOfUInt
// description:
// changes string to vector of unsigned integer. Format: n1,n2,n3, ...
// precondition: spaces between numbers. String can also be enclosed in "..."
// postcondition: the return vector is filled with the apropriate numbers
// error behaviour: quits, if precondition is not fullfilled.
// -----------------------------------------------------------
vector<unsigned int> sToVectorOfUInt( const string& s_orig) {
  string s = s_orig;
  vector<unsigned int> v;
  if (s[1] == '\'') {
    DEBUG_MSG("Removing colons!");
    ASSERT(s[s.size()-1]=='\'',exception);
#ifdef G_COMPILER
    s.remove( 0U, 1U ); // remove the first letter
    s.remove(s.size()-1U,1U); // remove last letter
#else
    s.erase( 0, 1 ); // remove the first letter
    s.erase(s.size()-1,1); 
#endif
  }
  istringstream ist(s.c_str()); // see Stroustrup chapter 21.5.3
  string w; // word
  while (ist >> w) {
    v.push_back(stoi(w));
    DUMP(w);
  }
  return v;
}


// changes integer into sting:
string itos( const int &i )
{
  string s;

  ostringstream os; 
  os << i << '\0';
  return s = os.str();
}

// changes unsigned integer into sting:
string uitos( const unsigned int &i )
{
  string s;

  ostringstream os; 
  os << i << '\0';
  return s = os.str();
}

// changes long into sting:
string ltos( const long &l )
{
  string s;

  ostringstream os; 
  os << l << '\0';
  return s = os.str();
}

// changes float into sting:
string ftos( const float &f )
{
  string s;

  ostringstream os; 
  os << f << '\0';
  return s = os.str();
}
// changes double into sting:
string dtos( const double &d )
{
  string s;

  ostringstream os; 
  os << d;// << '\0';
  return s = os.str();
}

// tokenize text
vector<string> getTokens(const string& text) 
{
  istringstream ist(text.c_str());
  char* charLine = new char[text.size()+1]; // size of string
  vector<string> v;
  string s;
  while (!ist.eof()) {
    ist >> charLine;
    s = charLine; // assignment of c-strings to string!
    //    DUMP(s);
    if (s != "") { 
      v.push_back(s);
    }
  }
  delete[] charLine;
  return v;
}

/** replace each occurence of c1 by c2 */
string
translate(const string& s, char c1, char c2)
{
  string t = s;
  for (unsigned int i = 0; i < t.size(); ++i) {
    if (t[i] == c1) {
      t[i] = c2;
    }
  }
  return t;
}

/* return vector with positions, at which character c is found in string */
vector<unsigned int>
findPositions(const string& s, char c)
{
  vector<unsigned int> result;
  for (unsigned int i = 0; i < s.size(); ++i) {
    if (s[i] == c) {
      result.push_back(i);
    }
  }
  return result;
}
